package datastructure.graph.有向图;

import java.util.LinkedList;
import java.util.Queue;
import java.util.Stack;

/**
 * 单点最短有向路径（BFS）
 * @author MaoLin Wang
 * @date 2020/2/2212:06
 */
public class BreadthFirstDirectedPaths {
    private final int MAX_LIMITATION=Integer.MAX_VALUE;
    private boolean[] marked;
    private int[] distTo;
    private int[] edgeTo;


    public BreadthFirstDirectedPaths(Digraph digraph,int s) {
        this.marked=new boolean[digraph.V()];
        this.distTo=new int[digraph.V()];
        this.edgeTo=new int[digraph.V()];
        for (int i = 0; i < digraph.V(); i++) {
            //初始化为最大值，表示不可达
            distTo[i]=MAX_LIMITATION;
        }
        bfs(digraph,s);
    }

    private void bfs(Digraph digraph, int v) {
        marked[v]=true;
        distTo[v]=0;
        Queue<Integer> queue=new LinkedList<>();
        queue.add(v);
        while (!queue.isEmpty()){
            int old = queue.poll();
            for(int w:digraph.adj(old)){
                if (!marked[w]){
                    edgeTo[w]=old;
                    marked[w]=true;
                    distTo[w]=distTo[v]+1;
                   queue.add(w);
                }
            }
        }
    }
    public boolean hasPathTo(int v) {
        validateVertex(v);
        return marked[v];
    }
    public Iterable<Integer> pathTo(int v) {
        validateVertex(v);

        if (!hasPathTo(v)) {
            return null;
        }
        Stack<Integer> path = new Stack<Integer>();
        int x;
        for (x = v; distTo[x] != 0; x = edgeTo[x]) {
            path.push(x);
        }
        path.push(x);
        return path;
    }
    private void validateVertex(int v) {
        int V = marked.length;
        if (v < 0 || v >= V) {
            throw new IllegalArgumentException("vertex " + v + " is not between 0 and " + (V-1));
        }
    }
    private void validateVertices(Iterable<Integer> vertices) {
        if (vertices == null) {
            throw new IllegalArgumentException("argument is null");
        }
        int V = marked.length;
        for (int v : vertices) {
            if (v < 0 || v >= V) {
                throw new IllegalArgumentException("vertex " + v + " is not between 0 and " + (V-1));
            }
        }
    }
}
